import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;

public class AnimationPanel extends JPanel implements Runnable, MouseListener {

	RopeState rs;
	
	ImageIcon backImage, fiTeamImage, saTeamImage;
	
	ImageIcon[] ropeCoverImages = new ImageIcon[8];
	int[][] ropeCoverPositions = { {216,511}, {216,514}, {216,517}, {216,519}, {404,111}, {401,113}, {399,115}, {398,118} };
	
	ImageIcon[][] ropeMovementImages = new ImageIcon[3][4];
	int[][] ropeMovementPositions = { {313,134}, {309,206}, {390,418} };
	
	ImageIcon[] countdownImages = new ImageIcon[6];
	
	ImageIcon disconnectedImage, restartImage;
	
	ImageIcon wonImage, lostImage;
	
    Thread animator;
    int delay;
	
	public AnimationPanel(RopeState rs) {
	
		super(null);
		setPreferredSize(new Dimension(800,600));
		
		this.rs = rs;
	
		// add mouseListner
		addMouseListener(this);
	
		// set the delay between screen updates
		delay = 50;

		// load the background image
		backImage = new ImageIcon("images/world.gif");
        while (backImage.getImageLoadStatus() != MediaTracker.COMPLETE);
		
		// load the team images
		fiTeamImage = new ImageIcon("images/peeps2.gif");
		while (fiTeamImage.getImageLoadStatus() != MediaTracker.COMPLETE);
		saTeamImage = new ImageIcon("images/peeps1.gif");
		while (saTeamImage.getImageLoadStatus() != MediaTracker.COMPLETE);

		// load the images that cover the excess rope
		for (int i=1; i<=2; i++) {
			for (int j=1; j<=4; j++) {
				ropeCoverImages[j+(4*(i-1))-1] = new ImageIcon("images/ropecover"+i+"_r"+j+".gif");
				while (ropeCoverImages[j+(4*(i-1))-1].getImageLoadStatus() != MediaTracker.COMPLETE);
			}
		}

		// load the images to animate the rope
		for (int i=0; i<3; i++) {
			for (int j=0; j<4; j++) {
				ropeMovementImages[i][j] = new ImageIcon("images/rope"+(i+1)+"_f"+(j+1)+".gif");
				while (ropeMovementImages[i][j].getImageLoadStatus() != MediaTracker.COMPLETE);
			}
		}
		
		// load the disconnected image
		disconnectedImage = new ImageIcon("images/disconnected.gif");
		while (disconnectedImage.getImageLoadStatus() != MediaTracker.COMPLETE);
		
		// load the countdown images
		for (int i=0; i<6; i++) {
			countdownImages[i] = new ImageIcon("images/no"+i+".gif");
			while (countdownImages[i].getImageLoadStatus() != MediaTracker.COMPLETE);
		}

		// load the restart button image
		restartImage = new ImageIcon("images/restart.gif");
		while (restartImage.getImageLoadStatus() != MediaTracker.COMPLETE);

		// load the won/lost images
		wonImage = new ImageIcon("images/youwon.gif");
		while (wonImage.getImageLoadStatus() != MediaTracker.COMPLETE);
		lostImage = new ImageIcon("images/youlost.gif");
		while (lostImage.getImageLoadStatus() != MediaTracker.COMPLETE);
		
	}

    public void start() {
		animator = new Thread(this);
		animator.start();
    }
	
    public void run() {
		// Remember the starting time
		long tm = System.currentTimeMillis();
		while (Thread.currentThread() == animator) {
		    // Display the next frame of animation.
		    repaint();

		    // Delay depending on how far we are behind.
		    try {
			tm += delay;
			Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
		    } catch (InterruptedException e) {
			break;
		    }
		}
    }

    public void stop() {
		animator = null;
    }

	public void mousePressed(MouseEvent e) {}

	public void mouseReleased(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

  	public void mouseExited(MouseEvent e) {}

	// restart game     	
	public void mouseClicked(MouseEvent e) {
	      if (e.getX() <= 800 && e.getX() >= 730
          	    && e.getY() <= 25 && e.getY() >= 0)
          	    rs.setGameState(RopeState.COUNTDOWN);	
	}

	public void paintComponent(Graphics g) {
	
		super.paintComponent(g);

		int offset = (rs.getRopePosition() * 80) / 1000;
		int ropeFrameNo = Math.abs((offset+80) % 4);

		// paint the background images
		backImage.paintIcon(this, g, 0,0);

		// paint the rope
		for (int i=0; i<3; i++)
			ropeMovementImages[i][ropeFrameNo].paintIcon(this, g, ropeMovementPositions[i][0], ropeMovementPositions[i][1]);
		
		// paint the teams
		fiTeamImage.paintIcon(this, g, 80+offset,38);		// x range 0-160
		saTeamImage.paintIcon(this, g, 298+offset,434);		// x range 218-378
		
		// paint over the rope
		for (int i=0; i<8; i++)
			ropeCoverImages[i].paintIcon(this, g, ropeCoverPositions[i][0], ropeCoverPositions[i][1]);

		// paint the rope forces
		g.setColor(Color.RED);
		g.setFont(new Font("Helvetica", Font.BOLD, 50));	
		if (rs.isConnected() || rs.isMaster()) { // force is unknown if we are the slave and we are disconnected
			if (rs.getMasterForce() < 10)
				g.drawString(""+rs.getMasterForce(), 585, 175);
			else if (rs.getMasterForce() < 100)
				g.drawString(""+rs.getMasterForce(), 572, 175);
			else if (rs.getMasterForce() < 1000)
				g.drawString(""+rs.getMasterForce(), 559, 175);
			else
				g.drawString(""+rs.getMasterForce(), 546, 175);
		} else { 
			g.drawString("?", 585, 175); 
		}	
		if (rs.isConnected() || ! rs.isMaster()) { // force is unknown if we are the master and we are disconnected
			if (rs.getSlaveForce() < 10)
				g.drawString(""+rs.getSlaveForce(), 205, 520);
			else if (rs.getSlaveForce() < 100)
				g.drawString(""+rs.getSlaveForce(), 192, 520);
			else if (rs.getSlaveForce() < 1000)
				g.drawString(""+rs.getSlaveForce(), 179, 520);
			else
				g.drawString(""+rs.getSlaveForce(), 166, 520);
		} else {
			g.drawString("?", 205, 520);
		}
		
		// paint the disconnected sign if necessary
		if (! rs.isConnected())
			disconnectedImage.paintIcon(this, g, 337, 251);
		
		// paint the countdown graphics
		if (rs.getGameState() == RopeState.COUNTDOWN) {
			long currentcount = rs.getElapsedTime();
			if (currentcount >= -5 && currentcount <= 0)
				countdownImages[Math.abs((int) currentcount)].paintIcon(this, g, 233, 139);
		}

		// paint the winning graphics
		if (rs.getGameState() == RopeState.GAMEOVER) {
			if ((rs.isMaster() && rs.getRopePosition() < -999) || (!rs.isMaster() && rs.getRopePosition() > 999))
				wonImage.paintIcon(this, g, 155, 255);
			else if ((!rs.isMaster() && rs.getRopePosition() < -999) || (rs.isMaster() && rs.getRopePosition() > 999))
				lostImage.paintIcon(this, g, 167, 253);
		}
		
		// paint the current time or status
		g.setColor(Color.LIGHT_GRAY);
		g.fillRect(730, (rs.isMaster()?24:0), 70, 35 );
		g.setColor(Color.BLACK);
		g.setFont(new Font("Helvetica", Font.BOLD, 12));
		if (rs.getGameState() == RopeState.GAMEOVER)
			g.drawString("Game over", 735, 22+(rs.isMaster()?24:0));
		else {
			g.drawString("Game time:", 734, 15+(rs.isMaster()?24:0));
			g.drawString(""+rs.getElapsedTime()+" seconds", 734, 28+(rs.isMaster()?24:0));
		}
		
		// paint the restart button
		if (rs.isMaster())
			restartImage.paintIcon(this, g, 730, 0);
	}

}
